import CryptoJS from 'crypto-js'
import { MutableRefObject } from 'react'

const httpUrl = new URL('https://spark-api.xf-yun.com/v3.5/chat')

const APPID = '75dc5707'
const API_SECRET = 'YWMyOGRlOGRiZDIwZDMwNTU1YjU0Yjcy'
const API_KEY = '781dde41ef975e1eb44908e0f77f877f'

const getWebsocketUrl = () => {
  return new Promise<string>((resolve) => {
    const apiKey = API_KEY
    const apiSecret = API_SECRET

    let url = 'wss://' + httpUrl.host + httpUrl.pathname

    const host = location.host
    const date = new Date().toUTCString()
    const algorithm = 'hmac-sha256'
    const headers = 'host date request-line'
    const signatureOrigin = `host: ${host}\ndate: ${date}\nGET ${httpUrl.pathname} HTTP/1.1`
    const signatureSha = CryptoJS.HmacSHA256(signatureOrigin, apiSecret)
    const signature = CryptoJS.enc.Base64.stringify(signatureSha)
    const authorizationOrigin = `api_key="${apiKey}", algorithm="${algorithm}", headers="${headers}", signature="${signature}"`
    const authorization = btoa(authorizationOrigin)
    url = `${url}?authorization=${authorization}&date=${date}&host=${host}`
    resolve(url)
  })
}

const dialogue = (
  question: string,
  ttsWSRef: MutableRefObject<WebSocket | null>,
  totalResRef: MutableRefObject<string>,
  onMessageReceived: () => void,
  endofJudgment?: (data: boolean) => void,
) => {
  getWebsocketUrl().then((url) => {
    if ('WebSocket' in window) {
      ttsWSRef.current = new WebSocket(url)
    } else {
      alert('浏览器不支持WebSocket')
      return
    }

    const webSocketSend = () => {
      const params = {
        header: {
          app_id: APPID,
          uid: 'fd3f47e4-d',
        },
        parameter: {
          chat: {
            domain: 'generalv3.5',
            temperature: 0.5,
            max_tokens: 1024,
          },
        },
        payload: {
          message: {
            text: [
              {
                role: 'user',
                content: question,
              },
            ],
          },
        },
      }
      ttsWSRef.current?.send(JSON.stringify(params))
    }

    const result = (resultData: any) => {
      const jsonData = JSON.parse(resultData)
      totalResRef.current += (jsonData.payload?.choices?.text[0]?.content || '').replace(
        /\n/g,
        '<br/>',
      )
      onMessageReceived()

      if (jsonData.header.code !== 0) {
        console.error(`${jsonData.header.code}:${jsonData.header.message}`)
        return
      }
      if (jsonData.header.code === 0 && jsonData.header.status === 2) {
        ttsWSRef.current?.close()
      }
    }

    if (ttsWSRef.current) {
      ttsWSRef.current.onopen = () => {
        if (endofJudgment) {
          endofJudgment(false)
        }
        webSocketSend()
      }
      ttsWSRef.current.onmessage = (e: any) => {
        result(e.data)
      }
      ttsWSRef.current.onerror = () => {
        ttsWSRef.current?.close()
      }
      ttsWSRef.current.onclose = () => {
        totalResRef.current = ''
        if (endofJudgment) {
          endofJudgment(true)
        }
      }
    }
  })
}

export default dialogue
